package org.koin.test.junit5;

import org.junit.jupiter.api.extension.*;
import org.koin.core.Koin;
import org.koin.core.KoinAppDeclaration;
import org.koin.core.KoinApplication;
import org.koin.core.context.DefaultContextExt;

public class KoinTestExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {

    private final static ExtensionContext.Namespace KOIN_STORE =
            ExtensionContext.Namespace.create("KOIN_STORE");
    public static volatile KoinTestExtension KOINTESTEXTENSIONINSTANCE;
    private KoinAppDeclaration appDeclaration;

    private KoinTestExtension(KoinAppDeclaration app) {
        this.appDeclaration = app;
    }

    public static KoinTestExtension INSTANCE(KoinAppDeclaration app) {

        if (null == KOINTESTEXTENSIONINSTANCE) {
            synchronized (KoinTestExtension.class) {
                if (null == KOINTESTEXTENSIONINSTANCE) {
                    KOINTESTEXTENSIONINSTANCE = new KoinTestExtension(app);
                }
            }
        }
        return KOINTESTEXTENSIONINSTANCE;

    }

    private static ExtensionContext.Store store(ExtensionContext context) {
        return context.getStore(KOIN_STORE);
    }

    @Override
    public void afterEach(ExtensionContext context) throws Exception {
        store(context).remove(Koin.class.getName());
        DefaultContextExt.stopKoin();
    }

    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
        Koin koin = DefaultContextExt.startKoin((KoinApplication) appDeclaration).getKoin();
        store(context).put(Koin.class.getName(), koin);
    }

    @Override
    public boolean supportsParameter(ParameterContext parameterContext,
                                     ExtensionContext extensionContext)
            throws ParameterResolutionException {
        return parameterContext.getParameter().getType() == Koin.class; //TODO
    }

    @Override
    public Object resolveParameter(ParameterContext parameterContext,
                                   ExtensionContext extensionContext)
            throws ParameterResolutionException {
        return store(extensionContext).get(Koin.class.getName());
    }
}
